home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 076-100 / disk_092 / uuencode / uudecode.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  6KB  |  285 lines

  1. /* #ifndef lint
  2. static char sccsid[] = "@(#)uudecode.c  5.3-1 (Berkeley) 4/10/85";
  3. #endif */
  4.  
  5. /* Written by Mark Horton */
  6. /* Modified by ajr (Alan J Rosenthatl,flaps@utcsri.UUCP) to use checksums */
  7. /* Modified by fnf (Fred Fish,well!fnf) to use Keith Pyle's suggestion for
  8.    compatibility */
  9. /* Modified by bcn (Bryce Nesbitt,ucbvax!cogsci!bryce) to fix some very
  10.    misleading error messages on the Amiga port, to fix a bug that prevented
  11.    decoding certain files, to work even if trailing spaces have been
  12.    removed from a file, to check the filesize (if present), to add some
  13.    error checking, and to loop for multiple decodes from a single file.
  14.    Also kludged around a missing string function in Aztec C */
  15.  
  16. /*
  17.  * uudecode [input]
  18.  *
  19.  * Decode a file encoded with uuencode.
  20.  */
  21.  
  22. #include <stdio.h>
  23. #include <ctype.h>
  24.  
  25. #ifdef AMIGA
  26. #define AMIGA_LATTICE        /* Set for Amiga Lattice C */
  27. #define MCH_AMIGA
  28. #define MPU68000
  29. #endif
  30.  
  31. #ifdef unix
  32. #include <pwd.h>
  33. #include <sys/types.h>
  34. #include <sys/stat.h>
  35. #endif
  36.  
  37. #define SUMSIZE 64
  38. #define DEC(c)    (((c) - ' ') & 077)    /* single character decode */
  39.  
  40. main(argc, argv)
  41. char **argv;
  42. {
  43. FILE    *in, *out;
  44. int    through_loop=0; /* Dejavu indicator */
  45. int    mode;        /* file's mode (from header) */
  46. long    filesize;    /* theoretical file size (from header) */
  47. char    dest[128];
  48. char    buf[80];
  49.  
  50. #ifdef AMIGA_LATTICE_OBSOLETE
  51. extern    int Enable_Abort;
  52.     Enable_Abort=1;
  53. #endif
  54.  
  55.     /* A filename can be specified to be uudecoded, or nothing can
  56.     be specified, and the input will come from STDIN */
  57.  
  58.     switch (argc)
  59.     {
  60.     case 1:
  61.     in=stdin;
  62.     break;
  63.  
  64.     case 2:
  65.     if ((in = fopen(argv[1], "r")) == NULL)
  66.         {
  67.         fprintf(stderr, "ERROR: can't find %s\n", argv[1]);
  68.         fprintf(stderr, "USAGE: uudecode [infile]\n");
  69.         exit(10);
  70.         }
  71.     break;
  72.  
  73.     default:
  74.     fprintf(stderr, "USAGE: uudecode [infile]\n");
  75.     exit(11);
  76.     break;
  77.     }
  78.  
  79.     /* Loop through file, searching for headers.  Decode anything with a
  80.        header, complain if there where no headers. */
  81.  
  82. for (;;)
  83. {
  84.     /* search file for header line */
  85.     for (;;)
  86.     {
  87.     if (fgets(buf, sizeof buf, in) == NULL)
  88.         {
  89.         if (!through_loop)
  90.         {
  91.         fprintf(stderr, "ERROR: no `begin' line!\n");
  92.         exit(12);
  93.         }
  94.         else
  95.         {
  96.         exit(0);
  97.         }
  98.         }
  99.     if (strncmp(buf, "begin ", 6) == 0)
  100.         break;
  101.     }
  102.     sscanf(buf, "begin %o %s", &mode, dest);
  103.  
  104. #ifdef unix
  105.     /* handle ~user/file format */
  106.     if (dest[0] == '~')
  107.     {
  108.     char *sl;
  109.     struct passwd *getpwnam();
  110.     char *index();
  111.     struct passwd *user;
  112.     char dnbuf[100];
  113.  
  114.     sl = index(dest, '/');
  115.     if (sl == NULL)
  116.         {
  117.         fprintf(stderr, "Illegal ~user\n");
  118.         exit(13);
  119.         }
  120.     *sl++ = 0;
  121.     user = getpwnam(dest+1);
  122.     if (user == NULL)
  123.         {
  124.         fprintf(stderr, "No such user as %s\n", dest);
  125.         exit(14);
  126.         }
  127.     strcpy(dnbuf, user->pw_dir);
  128.     strcat(dnbuf, "/");
  129.     strcat(dnbuf, sl);
  130.     strcpy(dest, dnbuf);
  131.     }
  132. #endif
  133.  
  134.     /* create output file */
  135.     if ((out = fopen(dest, "w")) == NULL)
  136.     {
  137.     fprintf(stderr, "ERROR: can't open output file %s\n", dest);
  138.     exit(15);
  139.     }
  140. #ifdef unix
  141.     chmod(dest, mode);
  142. #endif
  143.  
  144.     decode(in, out, dest);
  145.  
  146.     if (fgets(buf, sizeof buf, in) == NULL || strncmp(buf,"end",3))
  147.     {           /* don't be overly picky about newline ^ */
  148.     fprintf(stderr, "ERROR: no `end' line\n");
  149.     exit(16);
  150.     }
  151.  
  152.     if (!(fgets(buf,sizeof buf,in) == NULL || strncmp(buf,"size ",3)))
  153.     {
  154.     sscanf(buf, "size %ld", &filesize);
  155.     if (ftell(out) != filesize)
  156.         {
  157.         fprintf(stderr, "ERROR: file should have been %ld bytes long but was %ld.\n", filesize, ftell(out));
  158.         exit(17);
  159.         }
  160.     }
  161.     through_loop = 1;
  162. }   /* forever */
  163. }   /* main */
  164.  
  165. /*
  166.  * Copy from in to out, decoding as you go.
  167.  * If a return or newline is encountered too early in a line, it is
  168.  * assumed that means that some editor has truncated trailing spaces.
  169.  */
  170. decode(in, out, dest)
  171. FILE *in;
  172. FILE *out;
  173. char *dest;
  174. {
  175. char buf[80];
  176. char *bp;
  177. int nosum=0;
  178. #ifndef unix
  179. extern errno;
  180. #endif
  181. register int j;
  182. register int n;
  183. int checksum, line;
  184.  
  185.     for (line = 1; ; line++)    /* for each input line */
  186.     {
  187.     if (fgets(buf, sizeof buf, in) == NULL)
  188.         {
  189.         fprintf(stderr, "ERROR: input ended unexpectedly!\n");
  190.         exit(18);
  191.         }
  192.  
  193.     /* Pad end of lines in case some editor truncated trailing
  194.        spaces */
  195.  
  196.     for (n=0;n<79;n++)  /* search for first \r, \n or \000 */
  197.         {
  198.         if(buf[n]=='\r'||buf[n]=='\n'||buf[n]=='\000')
  199.         break;
  200.         }
  201.     for (;n<79;n++)     /* when found, fill rest of line with space */
  202.         {
  203.         buf[n]=' ';
  204.         }
  205.     buf[79]=0;        /* terminate new string */
  206.  
  207.     checksum = 0;
  208.     n = DEC(buf[0]);
  209.     if (n <= 0)
  210.         break;    /* 0 bytes on a line??    Must be the last line */
  211.  
  212.     bp = &buf[1];
  213.  
  214.     /* FOUR input characters go into each THREE output charcters */
  215.  
  216.     while (n >= 4)
  217.         {
  218.         j = DEC(bp[0]) << 2 | DEC(bp[1]) >> 4; putc(j, out); checksum += j;
  219.         j = DEC(bp[1]) << 4 | DEC(bp[2]) >> 2; putc(j, out); checksum += j;
  220.         j = DEC(bp[2]) << 6 | DEC(bp[3]);       putc(j, out); checksum += j;
  221.         checksum = checksum % SUMSIZE;
  222.         bp += 4;
  223.         n -= 3;
  224.         }
  225.  
  226.         j = DEC(bp[0]) << 2 | DEC(bp[1]) >> 4;
  227.         checksum += j;
  228.         if (n >= 1)
  229.             putc(j, out);
  230.         j = DEC(bp[1]) << 4 | DEC(bp[2]) >> 2;
  231.         checksum += j;
  232.         if (n >= 2)
  233.             putc(j, out);
  234.         j = DEC(bp[2]) << 6 | DEC(bp[3]);
  235.         checksum += j;
  236.         if (n >= 3)
  237.             putc(j, out);
  238.         checksum = checksum % SUMSIZE;
  239.         bp += 4;
  240.         n -= 3;
  241.  
  242. #ifndef unix
  243.      /* Error checking under UNIX??? You must be kidding... */
  244.      /* Check if an error occured while writing to that last line */
  245.     if (errno)
  246.         {
  247.         fprintf(stderr, "ERROR: error writing to %s\n",dest);
  248.         exit(19);
  249.         }
  250. #endif
  251.  
  252.     /* The line has been decoded; now check that sum */
  253.  
  254.     nosum |= !isspace(*bp);
  255.     if (nosum)            /* Is there a checksum at all?? */
  256.         {
  257.         if (checksum != DEC(*bp))    /* Does that checksum match? */
  258.         {
  259.         fprintf(stderr, "ERROR: checksum mismatch decoding %s, line %d.\n",dest, line);
  260.         }
  261.         }    /* sum */
  262.     }    /* line */
  263. }   /* function */
  264.  
  265. #ifdef unix
  266. /*
  267.  * Return the ptr in sp at which the character c appears;
  268.  * 0 if not found
  269.  */
  270. char *
  271. index(sp, c)
  272. register char *sp, c;
  273. {
  274.     do
  275.     {
  276.     if (*sp == c)
  277.         return(sp);
  278.     }
  279.     while (*sp++);
  280.  
  281.     return(0);
  282. }
  283. #endif unix
  284.  
  285.